﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OracleClient;
using System.Data;

namespace IBS
{
    public partial class IbsDataContext
    {
        /// <summary>
        /// Сохранение поставки в базу IBS
        /// </summary>
        /// <param name="delivery"></param>
        public Int64 SaveDelivery(Interfaces.IDelivery delivery, Int64 packageId)
        {
            var headerId = SaveDeliveryHeader(delivery, packageId);
            delivery.DeliveryItems.ToList().ForEach(r => SaveDeliveryItem(r, headerId));

            return headerId;
        }

        private long SaveDeliveryHeader(Interfaces.IDelivery delivery, Int64 packageId)
        {
            /// При загрузке накладных прихода/возврата необходимо формировать параметр DN_IBSNUM по следующему правилу:
            /// N – номер документа в Retalix;
            /// SiteIBSCode – код объекта в IBS;
            /// P1 = последние две цифры года документа деленные нацело на 10;
            /// P2 = нули, если длина номера документа меньше 5 символов, т.е. (длина N) + (длина P2) должна всегда  быть равна 5 символам;
            /// P3 = последняя цифра года документа;
            /// DN_IBSNUM – номер накладной в IBS;
            ///
            /// DN_IBSNUM = (P1) + (SiteIBSCode) + (P3) + (P2) + (N)
            ///
            /// Например:
            ///     N = 23
            ///     SiteIBSCode = 102
            ///     P1 = (07 / 10) = 0.7 = 1
            ///     P2 = 000
            ///     P3 = 7
            ///     DN_IBSNUM = 1102700023
            /// Изменение в ТЗ
            /// В существующем сервисе при формировании номера накладной используются последние пять цифр, 
            /// поэтому номера 1612091 и 1712091 для загрузчика одинаковы. 
            /// Возникает ошибка обработки. 
            /// В этой связи сервис должен использовать весь номер накладной при выгрузке/загрузке. 
            /// 
            /// Добавить обработку пустых номеров топливных накладных
            /// Для топливных накладных, в случае отсутствия номера у накладной, 
            /// сервис должен присваивать накладной номер (один и тот же для всех). Либо обрабатывать накладные без номера. 
            /// 
            /// Для товарных накладных при наличии номера товарной накладной более 18 символов загружать первые 18 символов названия.
            /// 
            /// Для топливных - добавить 1, для нетопливных - 0
            /// 
            ///  Для формирования «№ IBS» берем DocumentId
            ///  Для  «№ документа» берем ExternalDocumentId. Если ExternalDocumentId превышает 18 символов, обрезаем.

            if (String.IsNullOrEmpty(delivery.ExternalDeliveryNumber))
                delivery.ExternalDeliveryNumber = packageId.ToString();

            delivery.ExternalDeliveryNumber = (delivery.ExternalDeliveryNumber.Length > 18)
                ? delivery.ExternalDeliveryNumber.Substring(delivery.ExternalDeliveryNumber.Length - 18)
                : delivery.ExternalDeliveryNumber;

            var p_dn_docnum = delivery.DeliveryNumber;
            var year = delivery.DeliveryDate.ToString("yy");
            var deliveryNumber = delivery.DeliveryNumber;
            deliveryNumber = System.Text.RegularExpressions.Regex.Replace(deliveryNumber, @"[^\d]", "");
            var deliveryPrefix = delivery.DeliveryItems.Any(r => r.ItemId < 100) ? 1 : 0;

            deliveryNumber = String.IsNullOrEmpty(deliveryNumber)
                ? packageId.ToString()
                : deliveryNumber;

            deliveryNumber = (deliveryNumber.Length < 5)
                ? deliveryNumber.PadLeft(5, '0')
                : deliveryNumber;

            deliveryNumber = (deliveryNumber.Length > 18)
                ? deliveryNumber.Substring(deliveryNumber.Length - 18)
                : deliveryNumber;

            var DN_IBSNUM =
                Double.Parse(((int.Parse(year) / 10 + 1) % 10).ToString()
                + delivery.StoreId.ToString().Substring(delivery.StoreId.ToString().Length - 3)
                + year.Substring(1)
                + deliveryPrefix
                + deliveryNumber);

            /// p_type_trn
            /// 1 Приход
            /// 
            /// 2 Расход
            /// 4 Возврат
            using (var connection = new OracleConnection(this.connectionString))
            {
                connection.Open();
                using (var command = new OracleCommand())
                {
                    command.Connection = connection;
                    command.CommandType = CommandType.StoredProcedure;
                    command.CommandText = "ibsdbo.USP_ADD_DELIV_NOTE_EDEX";
                    command.Parameters.Clear();
                    command.Parameters.Add("p_DN_ID", OracleType.Number).Direction = ParameterDirection.Output;
                    command.Parameters.AddWithValue("p_type_trn", delivery.TypeId);
                    command.Parameters.AddWithValue("P_STATCODE", 21);
                    command.Parameters.AddWithValue("p_dn_ibsnum", DN_IBSNUM);
                    command.Parameters.AddWithValue("p_dn_ibsdate", delivery.BusinessDate);
                    command.Parameters.AddWithValue("p_supibscode", delivery.SupplierId);
                    command.Parameters.AddWithValue("p_siteibscode", delivery.StoreId);
                    command.Parameters.AddWithValue("p_dn_docnum", p_dn_docnum);
                    command.Parameters.AddWithValue("p_dn_docdate", delivery.DeliveryDate.Date);
                    command.Parameters.AddWithValue("p_dn_comment", DBNull.Value);
                    command.Parameters.AddWithValue("p_NUM_IMPORT", packageId);
                    command.ExecuteNonQuery();

                    return Convert.ToInt64(command.Parameters["p_DN_ID"].Value);
                }
            }
        }

        private void SaveDeliveryItem(Interfaces.IDeliveryItem item, long headerId)
        {
            using (var connection = new OracleConnection(this.connectionString))
            {
                connection.Open();
                using (var command = new OracleCommand())
                {
                    command.Connection = connection;
                    command.CommandType = CommandType.StoredProcedure;
                    command.CommandText = "ibsdbo.USP_ADD_DN_ITEM_EDEX";
                    command.Parameters.Clear();
                    command.Parameters.AddWithValue("p_DN_ID", headerId);
                    command.Parameters.AddWithValue("p_ITEMCODE", item.ItemId);
                    command.Parameters.AddWithValue("p_QTY", Math.Abs(item.Quantity));
                    command.Parameters.AddWithValue("p_CurPrice", item.CurrentPrice);
                    command.Parameters.AddWithValue("p_RblPrice", item.CurrentPrice);
                    command.Parameters.AddWithValue("p_AvPrice", item.AveragePrice);
                    command.Parameters.AddWithValue("p_RetPrice", item.RetailPrice);
                    command.Parameters.AddWithValue("p_vat_ibs", item.TaxPercent);
                    command.Parameters.AddWithValue("p_FDN_WEIGHT", item.Weight);
                    command.ExecuteNonQuery();
                }
            }
        }
    }
}
